package com.yumo.kangchenjunga.sms;

import java.time.Instant;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.google.common.collect.ImmutableMap;

import cn.leafcraft.utils.webutil.datetime.DateTimeUtils;

@Service
public final class SmsVerificationCodeService {

	private final Logger logger = LoggerFactory.getLogger(getClass());
	private final ConcurrentHashMap<String, VerificationCodeVo> map = new ConcurrentHashMap<>();
	private final Random random = new Random();
	private final RestTemplate restTemplate = new RestTemplate();

	@Value("${application.sms.url:}")
	private String smsUrl;
	@Value("${application.verification-code.template:}")
	private String template;
	@Value("${application.verification-code.debug-mode:false}")
	private boolean debugMode;

	public String generate(String key, String phone) {
		String serial = generateSerial();
		String code = generateCode();
		Instant now = DateTimeUtils.instantNow();

		map.put(key, new VerificationCodeVo(key, serial, code, now, now.plusSeconds(600)));
		sendSms(phone, serial, code);

		return serial;
	}

	private String generateSerial() {
		return null;
	}

	private String generateCode() {
		return StringUtils.leftPad(Integer.toString(random.nextInt(1_000_000)), 6, '0');
	}

	private void sendSms(String phone, String serial, String code) {
		String message = String.format(template, serial, code);

		if (!debugMode) {
			var result = restTemplate.getForObject(smsUrl, String.class,
					ImmutableMap.of("phone", phone, "message", message));

			logger.debug(result);
		} else {
			logger.info("phone: '{}', message: '{}'", phone, message);
		}
	}

	public boolean verify(String key, String serial, String verificationCode) {
		var vo = map.get(key);

		return vo != null && StringUtils.equals(vo.code, verificationCode)
				&& DateTimeUtils.instantNowBefore(vo.expired);
	}

}
